home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Common / src / diutil.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  10.6 KB  |  342 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DIUtil.cpp
  3. //
  4. // Desc: DirectInput framework class using semantic mapping.  Feel free to use 
  5. //       this class as a starting point for adding extra functionality.
  6. //
  7. // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #define DIRECTINPUT_VERSION 0x0800
  11. #include <basetsd.h>
  12. #include <tchar.h>
  13. #include <stdio.h>
  14. #include "DIUtil.h"
  15. #include "DXUtil.h"
  16.  
  17.  
  18.  
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Name: CInputDeviceManager()
  23. // Desc: Constructor 
  24. //-----------------------------------------------------------------------------
  25. CInputDeviceManager::CInputDeviceManager()
  26. {
  27.     HRESULT hr = CoInitialize(NULL);
  28.     m_bCleanupCOM = SUCCEEDED(hr);
  29.  
  30.     m_dwNumDevices = 0;
  31.     m_dwMaxDevices = 10;
  32.     m_pDI          = NULL;
  33.  
  34.     // Allocate DeviceInfo structs
  35.     m_pDevices = NULL;
  36.     m_pDevices = (DeviceInfo*) realloc( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  37.     ZeroMemory( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  38. }
  39.  
  40.  
  41.  
  42.  
  43. //-----------------------------------------------------------------------------
  44. // Name: ~CInputDeviceManager()
  45. // Desc: Destructor
  46. //-----------------------------------------------------------------------------
  47. CInputDeviceManager::~CInputDeviceManager()
  48. {
  49.     if( m_pDevices )
  50.     {
  51.         // Release() all devices
  52.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  53.         {
  54.             m_pDevices[i].pdidDevice->Unacquire();
  55.             m_pDevices[i].pdidDevice->Release();
  56.             m_pDevices[i].pdidDevice = NULL;
  57.         }
  58.  
  59.         free( m_pDevices );
  60.     }
  61.  
  62.     // Release() base object
  63.     SAFE_RELEASE( m_pDI );
  64.  
  65.     if( m_bCleanupCOM )
  66.         CoUninitialize();
  67. }
  68.  
  69.  
  70.  
  71.  
  72. //-----------------------------------------------------------------------------
  73. // Name: GetDevices()
  74. // Desc: Get the DeviceInfo array and number of devices
  75. //-----------------------------------------------------------------------------
  76. HRESULT CInputDeviceManager::GetDevices( DeviceInfo** ppDeviceInfo, 
  77.                                          DWORD* pdwCount )
  78. {
  79.     if( NULL==ppDeviceInfo || NULL==pdwCount )
  80.         return E_INVALIDARG;
  81.  
  82.     (*ppDeviceInfo) = m_pDevices;
  83.     (*pdwCount) = m_dwNumDevices;
  84.  
  85.     return S_OK;
  86. }
  87.  
  88.  
  89.  
  90.  
  91. //-----------------------------------------------------------------------------
  92. // Name: AddDevice()
  93. // Desc: Add the provided device to the list and perform initialization
  94. //-----------------------------------------------------------------------------
  95. HRESULT CInputDeviceManager::AddDevice( const DIDEVICEINSTANCE* pdidi, 
  96.                                         const LPDIRECTINPUTDEVICE8 pdidDevice )
  97. {
  98.     HRESULT hr;
  99.     DWORD   dwDeviceType = pdidi->dwDevType;
  100.  
  101.     pdidDevice->Unacquire();
  102.  
  103.     // Set the device's coop level
  104.     hr = pdidDevice->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  105.     if( FAILED(hr) )
  106.         return hr;
  107.  
  108.     // Add new DeviceInfo struct to list, and resize array if needed
  109.     m_dwNumDevices++;
  110.     if( m_dwNumDevices > m_dwMaxDevices )
  111.     {
  112.         m_dwMaxDevices += 10;
  113.         m_pDevices = (DeviceInfo*) realloc( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  114.         ZeroMemory( m_pDevices + m_dwMaxDevices - 10, 10*sizeof(DeviceInfo) );
  115.     }
  116.  
  117.     DWORD dwCurrentDevice = m_dwNumDevices-1;
  118.     m_pDevices[dwCurrentDevice].pdidDevice = pdidDevice;
  119.     m_pDevices[dwCurrentDevice].pdidDevice->AddRef();
  120.  
  121.     // Callback into the app so it can adjust the device and set
  122.     // the m_pDevices[dwCurrentDevice].pParam field with a device state struct
  123.     if( m_AddDeviceCallback )
  124.     {
  125.         hr = m_AddDeviceCallback( &m_pDevices[dwCurrentDevice], pdidi, m_AddDeviceCallbackParam ); 
  126.         if( FAILED(hr) )    
  127.             return hr;
  128.     }
  129.  
  130.     // Build the action map
  131.     hr = m_pDevices[dwCurrentDevice].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  132.     if( FAILED(hr) )
  133.         return hr;
  134.  
  135.     // Set the action map for the current device
  136.     hr = m_pDevices[dwCurrentDevice].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  137.     if( FAILED(hr) )
  138.         return hr;
  139.  
  140.     // Continue enumerating suitable devices
  141.     return S_OK;
  142. }
  143.  
  144.  
  145.  
  146.  
  147. //-----------------------------------------------------------------------------
  148. // Name: EnumSuitableDevicesCB()
  149. // Desc: Callback function for device enumeration. Adds all devices which
  150. //       met the search criteria
  151. //-----------------------------------------------------------------------------
  152. BOOL CALLBACK EnumSuitableDevicesCB( LPCDIDEVICEINSTANCE pdidi, 
  153.                                      LPDIRECTINPUTDEVICE8 pdidDevice, 
  154.                                      DWORD dwFlags, DWORD dwDeviceRemaining,
  155.                                      VOID* pContext )
  156. {
  157.     // Add the device to the device manager's internal list
  158.     ((CInputDeviceManager*)pContext)->AddDevice( pdidi, pdidDevice );
  159.  
  160.     // Continue enumerating suitable devices
  161.     return DIENUM_CONTINUE;
  162. }
  163.  
  164.  
  165.  
  166.  
  167. //-----------------------------------------------------------------------------
  168. // Name: SetActionFormat()
  169. // Desc: Set the action format to the provided DIACTIONFORMAT structure, and
  170. //       destroy and recreate device list if flagged
  171. //-----------------------------------------------------------------------------
  172. HRESULT CInputDeviceManager::SetActionFormat( DIACTIONFORMAT& diaf, BOOL bReenumerate )
  173. {
  174.     HRESULT hr = S_OK;
  175.  
  176.     // Store the new action format
  177.     m_diaf = diaf;
  178.  
  179.     // Only destroy and re-enumerate devices if the caller explicitly wants to. The 
  180.     // device list may be used within a loop, and kicking off an enumeration while 
  181.     // the device array is in use would cause problems.
  182.     if( bReenumerate )
  183.     {
  184.         // Cleanup any previously enumerated devices
  185.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  186.         {
  187.             m_pDevices[i].pdidDevice->Unacquire();
  188.             m_pDevices[i].pdidDevice->Release();
  189.             m_pDevices[i].pdidDevice = NULL;
  190.         }
  191.         m_dwNumDevices = 0;
  192.  
  193.         // Enumerate suitable DirectInput devices
  194.         hr = m_pDI->EnumDevicesBySemantics( m_strUserName, &m_diaf, 
  195.                                             EnumSuitableDevicesCB, this, 0L );
  196.         if( FAILED(hr) )
  197.             return hr;
  198.     }
  199.     else // Just apply the new maps.
  200.     {
  201.         // Devices must be unacquired to have a new action map set.
  202.         UnacquireDevices();
  203.  
  204.         // Apply the new action map to the current devices.
  205.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  206.         {
  207.             hr = m_pDevices[i].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  208.             if( FAILED(hr) )
  209.                 return hr;
  210.  
  211.             hr = m_pDevices[i].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  212.             if( FAILED(hr) )
  213.                 return hr;
  214.         }
  215.     }
  216.  
  217.     if( FAILED(hr) )
  218.         return hr;
  219.  
  220.     return S_OK;
  221. }
  222.  
  223.  
  224.  
  225.  
  226. //-----------------------------------------------------------------------------
  227. // Name: Create()
  228. // Desc: Create DirectInput object and perform initialization
  229. //-----------------------------------------------------------------------------
  230. HRESULT CInputDeviceManager::Create( HWND hWnd, TCHAR* strUserName, 
  231.                                      DIACTIONFORMAT& diaf,
  232.                                      LPDIMANAGERCALLBACK AddDeviceCallback, 
  233.                                      LPVOID pCallbackParam )
  234. {
  235.     HRESULT hr;
  236.  
  237.     // Store data
  238.     m_hWnd        = hWnd;
  239.     m_strUserName = strUserName;
  240.     m_AddDeviceCallback = AddDeviceCallback;
  241.     m_AddDeviceCallbackParam = pCallbackParam;
  242.     
  243.     // Create the base DirectInput object
  244.     hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  245.                               IID_IDirectInput8, (VOID**)&m_pDI, NULL );
  246.     if( FAILED(hr) )
  247.         return hr;
  248.  
  249.     hr = SetActionFormat( diaf, TRUE );
  250.     if( FAILED(hr) )
  251.         return hr;
  252.  
  253.     return S_OK;
  254. }
  255.  
  256.  
  257.  
  258.  
  259. //-----------------------------------------------------------------------------
  260. // Name: ConfigureDevices()
  261. // Desc: Pause input and display the device configuration UI
  262. //-----------------------------------------------------------------------------
  263. HRESULT CInputDeviceManager::ConfigureDevices( HWND hWnd, IUnknown* pSurface,
  264.                                                VOID* ConfigureDevicesCB,
  265.                                                DWORD dwFlags, LPVOID pvCBParam )
  266. {
  267.     HRESULT hr;
  268.  
  269.     // Initialize all the colors here
  270.     DICOLORSET dics;
  271.     ZeroMemory(&dics, sizeof(DICOLORSET));
  272.     dics.dwSize = sizeof(DICOLORSET);
  273.  
  274.     // Fill in all the params
  275.     DICONFIGUREDEVICESPARAMS dicdp;
  276.     ZeroMemory(&dicdp, sizeof(dicdp));
  277.     dicdp.dwSize = sizeof(dicdp);
  278.     dicdp.dwcFormats     = 1;
  279.     dicdp.lprgFormats    = &m_diaf;
  280.     dicdp.hwnd           = hWnd;
  281.     dicdp.lpUnkDDSTarget = pSurface;
  282.  
  283.     if( m_strUserName )
  284.     {
  285.         dicdp.dwcUsers       = 1;
  286.         dicdp.lptszUserNames = m_strUserName;
  287.     }
  288.  
  289.     // Unacquire the devices so that mouse doesn't control the game while in control panel
  290.     UnacquireDevices();
  291.  
  292.     hr = m_pDI->ConfigureDevices( (LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCB, 
  293.                                   &dicdp, dwFlags, pvCBParam );
  294.     if( FAILED(hr) )
  295.         return hr;
  296.  
  297.     if( dwFlags & DICD_EDIT )
  298.     {
  299.         // Re-set up the devices
  300.         hr = SetActionFormat( m_diaf, TRUE );
  301.         if( FAILED(hr) )
  302.             return hr;
  303.     }
  304.  
  305.     return S_OK;
  306. }
  307.  
  308.  
  309.  
  310. //-----------------------------------------------------------------------------
  311. // Name: UnacquireDevices()
  312. // Desc: Unacquire all devices in the member list
  313. //-----------------------------------------------------------------------------
  314. VOID CInputDeviceManager::UnacquireDevices()
  315. {
  316.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  317.         m_pDevices[i].pdidDevice->Unacquire();
  318. }
  319.  
  320.  
  321.  
  322.  
  323. //-----------------------------------------------------------------------------
  324. // Name: SetFocus()
  325. // Desc: Sets the DirectInput focus to a new HWND
  326. //-----------------------------------------------------------------------------
  327. VOID CInputDeviceManager::SetFocus( HWND hWnd ) 
  328. {
  329.     m_hWnd = hWnd;
  330.  
  331.     UnacquireDevices();
  332.  
  333.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  334.     {
  335.         // Set the device's coop level
  336.         m_pDevices[i].pdidDevice->SetCooperativeLevel( m_hWnd, 
  337.                                         DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  338.     }
  339. }
  340.  
  341.  
  342.